﻿using ECommerce.Web.Models;
using Machine.Specifications;

namespace Entity_equality_specs
{
    [Subject("Entity equality")]
    public class When_comparing_entities_with_the_same_id
    {
        private static ConcreteEntity1 x1;
        private static ConcreteEntity1 y1;
        private static ConcreteEntity1 z1;
        private static ConcreteEntity2 x2;

        Establish context = () =>
            {
                x1 = new ConcreteEntity1() { Id = 1 };
                y1 = new ConcreteEntity1() { Id = 1 };
                z1 = new ConcreteEntity1() { Id = 1 };
                x2 = new ConcreteEntity2() { Id = 1 };
            };

        It should_be_reflective = () =>
            {
                x1.Equals(x1).ShouldBeTrue();
            };

        It should_be_symmetric = () =>
            {
                x1.Equals(y1).ShouldBeTrue();
                y1.Equals(x1).ShouldBeTrue();
            };

        It should_be_transitive = () =>
            {
                x1.Equals(y1).ShouldBeTrue();
                y1.Equals(z1).ShouldBeTrue();
                x1.Equals(z1).ShouldBeTrue();
            };

        It should_be_consistent = () =>
            {
                x1.Equals(y1).ShouldBeTrue();
                x1.Equals(y1).ShouldBeTrue();
            };

        It should_return_the_same_hash_code_for_the_same_type = () =>
            {
                x1.GetHashCode().ShouldEqual(y1.GetHashCode());
            };

        It should_return_different_hash_codes_for_different_types = () =>
            {
                x1.GetHashCode().ShouldNotEqual(x2.GetHashCode());
            };
    }

    [Subject("Entity equality")]
    public class When_comparing_entities_with_uninitialized_ids
    {
        private static ConcreteEntity1 x;
        private static ConcreteEntity1 y;

        Establish context = () =>
            {
                x = new ConcreteEntity1();
                y = new ConcreteEntity1();
            };

        It should_not_be_equal = () =>
            {
                x.Equals(y).ShouldBeFalse();
            };

        It should_return_different_hash_codes = () =>
            {
                x.GetHashCode().ShouldNotEqual(y.GetHashCode());
            };
    }

    [Subject("Entity equality")]
    public class When_comparing_entities_with_different_ids
    {
        private static ConcreteEntity1 x;
        private static ConcreteEntity1 y;

        Establish context = () =>
            {
                x = new ConcreteEntity1() { Id = 1 };
                y = new ConcreteEntity1() { Id = 2 };
            };

        It should_not_be_equal = () =>
            {
                x.Equals(y).ShouldBeFalse();
            };

        It should_return_different_hash_codes = () =>
            {
                x.GetHashCode().ShouldNotEqual(y.GetHashCode());
            };
    }

    [Subject("Entity equality")]
    public class When_an_entities_id_is_changed
    {
        private static ConcreteEntity1 x;
        private static int hashCode;

        Establish context = () =>
            {
                x = new ConcreteEntity1() { Id = 1 };

                hashCode = x.GetHashCode();
            };

        Because of = () =>
            {
                x.Id = 2;
            };

        It should_maintain_the_same_hash_code = () =>
            {
                hashCode.ShouldEqual(x.GetHashCode());
            };
    }

    public class ConcreteEntity1 : Entity { }
    public class ConcreteEntity2 : Entity { }
}
